<?php

namespace App\Http\Controllers\OpenShop\Feishu;

use App\Console\Commands\OpenShop\SkipStepMultiple;
use App\Enums\BaseErrorCode;
use App\Enums\OpenShop\InvestmentPromotion\OpenShopCacheEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Enums\OpenShop\InvestmentPromotion\UserOrderEnum;
use App\Enums\OpenShop\MissionTemplateEnum;
use App\Events\OpenShop\OrderPaymentSucceededEvent;
use App\Events\OpenShop\UserContractCreatedEvent;
use App\Exceptions\Custom\ResponseHttpException;
use App\Http\Controllers\BaseController;
use App\Http\Validate\OpenShop\InvestmentPromotion\OrderNewValidate;
use App\Http\Validate\OpenShop\InvestmentPromotion\OrderValidate;
use App\Http\Validate\OpenShop\InvestmentPromotion\UserContractValidate;
use App\Http\Validate\OpenShop\Renew\RenewValidate;
use App\Library\FeiShu\SendFs;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrderTagsMappingModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderPayHistoryModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserContractModel;
use App\Remote\Rms\RmsShopRemote;
use App\Service\BaseService;
use App\Service\OpenShop\Feishu\PermissionService;
use App\Service\OpenShop\Feishu\UserExtContractService;
use App\Service\OpenShop\FeishuMini\ShopService;
use App\Service\OpenShop\Order\OrderTagsService;
use App\Service\OpenShop\OrderService;
use App\Service\OpenShop\SiteLocation\SiteLocationService;
use App\Service\OpenShop\User\RmsUserService;
use App\Service\OpenShop\UserContractService;
use App\Service\Renew\RenewOrderService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Validation\ValidationException;
use Kuafu\GeneralFs\BuildFs;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class SignOrderController extends BaseController
{
    public function overview(Request $request)
    {
        $userId         = getRmsUserInfoByAuth()->id;
        $dataPermission = PermissionService::dataPermission(PermissionService::URI_SIGN_ORDER);
        if ($dataPermission == PermissionService::PERMISSION_DENY) {
            return $this->fail(1, '权限不足');
        }

        // isAll && 原生sql
        $orderPermission = (new PermissionService)->getOrderPermissionDataOrder($dataPermission, $userId);
        $lists           = OrderService::overview($orderPermission);

        return $this->success(['lists' => $lists]);
    }

    public function preparationOverview(Request $request)
    {
        $userId         = getRmsUserInfoByAuth()->id;
        $dataPermission = PermissionService::dataPermission(PermissionService::URI_SIGN_ORDER);
        if ($dataPermission == PermissionService::PERMISSION_DENY) {
            return $this->fail(1, '权限不足');
        }

        // isAll && 原生sql
        $orderPermission = (new PermissionService)->getOrderPermissionDataOrder($dataPermission, $userId);
        $lists           = OrderTagsService::preparationOverview($orderPermission);

        return $this->success(['lists' => $lists]);
    }


    /**
     * @param Request $request
     * @param int $source 默认0 1-筹备订单
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function index(Request $request, $source = 0)
    {
        $province          = $request->get('province');
        $city              = $request->get('city');
        $area              = $request->get('area', '');
        $contractStartTime = $request->get('contractStartTime', '');
        $contractEndTime   = $request->get('contractEndTime', '');
        $siteStartTime     = $request->get('siteStartTime', '');
        $siteEndTime       = $request->get('siteEndTime', '');
        $manager           = $request->get('manager', '');
        $pageSize          = $request->get('pageSize', 10);
        $pageNum           = $request->get('pageNum', 1);
        $shopCode          = (int)$request->get('shopCode', 0);
        $merchantName      = (string)$request->get('merchantName', '');
        $orderNo           = (string)$request->get('orderNo', '');
        $shopPattern       = (string)$request->get('shopPattern', '');
        $stepStatusLists   = (string)$request->get('stepStatusStr');
        if ($stepStatusLists) {
            $stepStatusLists = explode(',', (string)$request->get('stepStatusStr'));
        } else {
            $stepStatusLists = [];
        }

        if (mb_strlen($contractStartTime)) {
            $contractStartTime = strtotime($contractStartTime . ' 00:00:00');
        }
        if (mb_strlen($contractEndTime)) {
            $contractEndTime = strtotime($contractEndTime . ' 23:59:59');
        }

        if (mb_strlen($siteStartTime)) {
            $siteStartTime = strtotime($siteStartTime . ' 00:00:00');
        }
        if (mb_strlen($siteEndTime)) {
            $siteEndTime = strtotime($siteEndTime . ' 23:59:59');
        }

        $branch             = (string)$request->get('branch', '');         //分公司
        $scheduledStartTime = $request->get('scheduledStartTime', '');     //预计开业时间选择
        $scheduledEndTime   = $request->get('scheduledEndTime', '');
        if (mb_strlen($scheduledStartTime)) {
            $scheduledStartTime = strtotime($scheduledStartTime . ' 00:00:00');
        }
        if (mb_strlen($scheduledEndTime)) {
            $scheduledEndTime = strtotime($scheduledEndTime . ' 23:59:59');
        }
        $startBusinessStartTime = $request->get('startBusinessStartTime', '');     //开业时间选择
        $startBusinessEndTime   = $request->get('startBusinessEndTime', '');
        if (mb_strlen($startBusinessStartTime)) {
            $startBusinessStartTime = strtotime($startBusinessStartTime . ' 00:00:00');
        }
        if (mb_strlen($startBusinessEndTime)) {
            $startBusinessEndTime = strtotime($startBusinessEndTime . ' 23:59:59');
        }
        $dataPermission = PermissionService::dataPermission(PermissionService::URI_SIGN_ORDER);
        $preparationUid  = 0;
        $reason = $preparationStartTime = $preparationEndTime = $preparationStartDay = $preparationEndDay = '';
        $tagId = (string)$request->get('tagId', '');     //筹备标签Id
        if ($tagId) {
            $tagId = explode(',', $tagId);
        }
        if ($source) {//筹备订单
            $preparationUid       = (int)$request->get('preparationUid', 0);     //筹备顾问id
            $reason               = (string)$request->get('reason', '');//筹备异常原因
            $preparationStartTime = $request->get('preparationStartTime', '');//筹备开始时间选择
            $preparationEndTime   = $request->get('preparationEndTime', '');
            if (mb_strlen($preparationStartTime)) {
                $preparationStartTime = strtotime($preparationStartTime . ' 00:00:00');
            }
            if (mb_strlen($preparationEndTime)) {
                $preparationEndTime = strtotime($preparationEndTime . ' 23:59:59');
            }
            $preparationStartDay = $request->get('preparationStartDay', '');     //筹备累计耗时天数
            $preparationEndDay   = $request->get('preparationEndDay', '');       //筹备累计耗时天数
            if (!$stepStatusLists) {
                $stepStatusLists = MissionTemplateEnum::PREPARE_STATUS_NEW;//筹备中状态
            }
        }
        $investmentManagerId    = (int)$request->get('investmentManagerId', 0);                        //开发顾问id
        $inviterId              = (string)$request->get('inviterId', '');                              //推荐人id
        $departmentName         = (string)$request->get('departmentName', '');                         //部门名称
        $mode                   = (int)$request->get("mode", 0);                                       //新店加盟模式
        $shopIds                = (string)$request->get('shopIds', '');                                //门店id 多个逗号隔开
        $investmentConsultantId = (int)$request->get('investmentConsultantId', 0);                        //招商顾问id

        $shopIds = $shopIds ? explode(',', $shopIds) : [];

        return $this->success(
            OrderService::getlist(
                $province, $city, $area, $contractStartTime, $contractEndTime,
                $manager, $pageSize, $pageNum, $dataPermission, $shopCode, $merchantName, $orderNo, $stepStatusLists,
                $siteStartTime, $siteEndTime, $source, $branch, $preparationUid, $reason, $scheduledStartTime,
                $scheduledEndTime, $preparationStartTime, $preparationEndTime, $startBusinessStartTime, $startBusinessEndTime,
                $preparationStartDay, $preparationEndDay, $tagId, $investmentManagerId, $inviterId, $departmentName,
                $mode, $shopPattern, $shopIds, $investmentConsultantId
            )
        );
    }

    //订单状态单独接口
    public function diff(Request $request)
    {
        // isAll && 原生sql
        $dataPermission  = PermissionService::dataPermission(PermissionService::URI_SIGN_ORDER);
        $orderPermission = (new PermissionService)->getOrderPermissionDataOrder($dataPermission, getRmsUserId());

        return $this->success(OrderService::getDifferentV2($orderPermission));
    }

    public function orderFilterTemplate(): JsonResponse
    {
        $status = UserOrderEnum::STATUS_MAP;
        $data   = [];
        foreach ($status as $k => $val) {
            $data[] = [
                'id'   => $k,
                'name' => $val
            ];
        }
        $openShopStatus = UserOrderEnum::STEP_FORMAT_FOREFRONT;
        $openShopData   = [];
        foreach ($openShopStatus as $k => $val) {
            $openShopData[] = [
                'id'   => $k,
                'name' => $val
            ];
        }

        $openShopData[] = [
            'id'   => MissionTemplateEnum::STEP_STATUS_100,
            'name' => MissionTemplateEnum::STEP_STATUS_TEXT[MissionTemplateEnum::STEP_STATUS_100]
        ];
        return $this->success([
            'status'         => $data,
            'openShopStatus' => $openShopData
        ]);
    }

    /**
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException|GuzzleException
     */
    public function detail(Request $request, string $orderNo): JsonResponse
    {
        OrderValidate::detailValidate($request->merge(['orderNo' => $orderNo])->all());
        $dataPermission = PermissionService::dataPermission();
        return $this->success(OrderService::detail($orderNo, $dataPermission));
    }


    /**
     * 作废订单
     *
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function invalidOrder(Request $request, string $orderNo): JsonResponse
    {
        $params = (object)OrderNewValidate::invalidOrderValidate($request->merge(['orderNo' => $orderNo])->all());
        OrderService::invalidOrder(getRmsUserInfoByAuth()->id, $params);
        return $this->success();
    }

    /**
     * 支付记录
     *
     * @param string $orderNo
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     * @throws Exception
     */
    public function orderPayHistory(string $orderNo): JsonResponse
    {
        $params = \App\Http\Validate\OpenShop\ShopLocation\OrderValidate::payDetailValidate([
            "orderNo" => $orderNo
        ]);
        return $this->success(OrderService::orderPayHistory($params->orderNo));
    }

    /**
     * 创建合同
     * @param string $orderNo
     * @return JsonResponse
     */
    public function createContract(string $orderNo): JsonResponse
    {
        // 同一个orderNo不允许并发请求
        $lockKey = OpenShopCacheEnum::getLockCreateContract($orderNo);
        if (!Redis::setnx($lockKey, time())) {

            // 防止死锁
            $lock_time = Redis::get($lockKey);
            if (($lock_time + 5) < time()) {
                Redis::del($lockKey);
            } else {
                return $this->fail(1, '您的操作太频繁，请稍后再试~');
            }
        }

        $createContract = UserExtContractService::orderNotify($orderNo);

        // 创建合同日志
        if ($createContract == '') {
            $contractId = (int)OpenShopUserContractModel::getUserIdByOrderNo($orderNo);
            event(new UserContractCreatedEvent($contractId, getRmsUserInfoByAuth()->id ?? 0));
        }

        return $this->success(["signUrl" => UserExtContractService::$signUrl]);
    }

    /**
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     * @throws Exception
     */
    public function submitOrderProof(Request $request, string $orderNo): JsonResponse
    {
        $this->validate($request, [
            'proof'              => 'required|array',
            'proof.*.img'        => 'required|string', // 支付凭证图片，私有OSS
            'proof.*.price'      => 'required|int|min:1',  // 本次凭证金额，人民币分
            'proof.*.payChannel' => 'required|int|in:' . implode(',', array_keys(OpenShopSignOrderPayHistoryModel::PAY_CHANNELS)),  // 支付渠道 OpenShopSignOrderPayHistoryModel
            'proof.*.flowNumber' => 'present|string', // 银行流水单号，目前默认是招商银行。空字符串代表未到账
        ]);
        OrderService::submitOrderProof(getRmsUserInfoByAuth(), $orderNo, $request->all());
        return $this->success();
    }

    public function queryAvailableFlows(Request $request)
    {
        $this->validate($request, [
            'date'    => 'required|date',
            'name'    => 'sometimes|string',
            'account' => 'sometimes|string',
            'amount'  => 'required|int|min:1', // 人民币分
        ]);
        $pageNum  = $request->get('pageNum', 1);
        $pageSize = $request->get('pageSize', 10);

        return $this->success(OrderService::queryAvailableFlows($request->date, (int)$request->amount,
            (string)$request->name, (string)$request->account, $pageNum, $pageSize));

    }

    /**
     * 更换经理
     *
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public function changeManager(Request $request, int $id): JsonResponse
    {
        $params = OrderValidate::changeManagerValidate($request->merge(["id" => $id])->all());
        OrderService::changeManager(getRmsUserInfoByAuth(), $params);
        return $this->success();
    }

    /**
     * 更换经理
     *
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ValidationException
     * @throws Exception|GuzzleException
     */
    public function getOrderCityFee(Request $request, string $orderNo): JsonResponse
    {
        OrderValidate::getOrderCityFeeValidate($request->merge(["orderNo" => $orderNo])->all());
        return $this->success(OrderService::getOrderCityFee($orderNo));
    }

    /**
     * 作废类型
     *
     * @param string $orderNo
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     * @throws Exception
     */
    public function invalidOrderType(string $orderNo): JsonResponse
    {
        OrderNewValidate::invalidOrderTypeValidate(["orderNo" => $orderNo]);
        return $this->success(OrderService::invalidOrderType($orderNo));
    }


    /**
     * 筹备订单
     * @param Request $request
     * @return JsonResponse
     */
    public function preparationList(Request $request): JsonResponse
    {
        return self::index($request, 1);
    }

    /**
     * 筹备订单修改
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ValidationException
     * @throws Exception
     */
    public function preparationUpdate(Request $request, string $orderNo): JsonResponse
    {
        OrderValidate::detailValidate($request->merge(['orderNo' => $orderNo])->all());
        $scheduledTime      = (string)$request->get('scheduledTime', '');    //预计开业时间
        $preparationStatus  = (int)$request->get('preparationStatus', 0);    //筹备状态 1-正常 2-异常
        $preparationReason  = (string)$request->get('preparationReason', '');//异常原因类型
        $preparationDesc    = (string)$request->get('preparationDesc', '');  //异常原因说明
        $pendingTermination = (int)$request->get('pendingTermination', 0);   //门店待解约状态 1-正常 2-待解约
        $log                = $request->get('log', []);                      //筹备日志
        $type               = (string)$request->get('type', 'preparation');  //类型 preparation-筹备 siteLocation-选址
        $shopPattern        = (int)$request->get('shopPattern', 0);
        $patternType        = (array)$request->get('patternType', []);

        if ($preparationStatus > 0 && !in_array($preparationStatus, [OpenShopOrderTagsMappingModel::TAG_TYPE_1, OpenShopOrderTagsMappingModel::TAG_TYPE_2])) {
            return BaseService::throwErr("筹备状态参数错误");
        }
        if ($pendingTermination > 0 && !in_array(
                $pendingTermination, [
                OpenShopOrderTagsMappingModel::TAG_TYPE_1, OpenShopOrderTagsMappingModel::TAG_TYPE_2,
                OpenShopOrderTagsMappingModel::TAG_TYPE_3, OpenShopOrderTagsMappingModel::TAG_TYPE_17, OpenShopOrderTagsMappingModel::TAG_TYPE_18
            ]
            )) {
            return BaseService::throwErr("门店待解约状态参数错误");
        }
        $rmsUserId = getRmsUserId();
        $userName  = getRmsUserInfoByAuth()->username;

        // rms门店属性
        $shopAttributes['shopType']                  = (string)$request->get('shopType', '');// 店型
        $shopAttributes['siteSelection']             = (string)$request->get('siteSelection', '');// 选址场景
        $shopAttributes['siteSelectionGrade']        = (string)$request->get('siteSelectionGrade', '');// 场景等级
        $shopAttributes['posLine']                   = (string)$request->get('posLine', '');// 点餐动线
        $shopAttributes['engineeringExhibitionArea'] = (string)$request->get('engineeringExhibitionArea', '');// 工程条件-展面
        $shopAttributes['engineeringArea']           = (string)$request->get('engineeringArea', '');// 工程条件-面积
        $shopAttributes['engineeringElectricity']    = (string)$request->get('engineeringElectricity', '');// 工程条件-电量
        $shopAttributes['engineeringDepth']          = (string)$request->get('engineeringDepth', '');// 工程条件-进深
        $shopAttributes['menuLevel']                 = (string)$request->get('menuLevel', '');// 菜单等级
        $shopAttributes['sellingCategory']           = (string)$request->get('sellingCategory', '');// 售卖品类

        // 修改筹备信息顺便修改门店模式
//        SiteLocationService::updateShopPattern($orderNo, $shopPattern, $patternType,true, $rmsUserId, $userName);

        return $this->success(
            OrderService::preparationUpdate(
                $orderNo, $scheduledTime, $preparationStatus, $preparationReason, $preparationDesc, $pendingTermination,
                $log, $rmsUserId, $userName, $type, $shopAttributes
            )
        );
    }

    /**
     * 筹备订单日志
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     * @throws ValidationException
     */
    public function preparationLog(Request $request, string $orderNo): JsonResponse
    {
        OrderValidate::detailValidate($request->merge(['orderNo' => $orderNo])->all());
        $type = (string)$request->get('type', 'preparation');  //类型 preparation-筹备 siteLocation-选址
        return $this->success(OrderService::preparationLog($orderNo));
    }

    /**
     * 查询飞书用户和一级部门
     * @param Request $request
     * @return JsonResponse
     */
    public function feishuUserDepartmentList(Request $request): JsonResponse
    {
        return $this->success(OrderService::getFeishuUserDepartmentList());
    }

    /**
     * 延期订单
     *
     * @return JsonResponse
     * @throws ValidationException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws Exception
     */
    public function deferOrder(): JsonResponse
    {
        RenewOrderService::renewDeferOrder(RenewValidate::deferOrderValidate());
        return $this->success();
    }

    public function skipPartPay(Request $request)
    {
        $orderNo = $request->get('orderNo');

        $this->validate($request, [
            'orderNo' => 'required|string',
        ]);

        if (config('app.env') == 'pre') {
            return $this->fail(400, '不允许pre环境执行');
        }

        $userName = getRmsUserInfoByAuth()->username;

        $this->signOrderModel = OpenShopSignOrderModel::query()->where('orderNo', $orderNo)->first();
        if (!$this->signOrderModel) {
            return $this->fail(400, '请检查订单号是否有误');
        }

        if ($this->signOrderModel->step != 3) {
            return $this->fail(400, '仅支持部分支付的订单跳流程');
        }

        $this->signOrderModel->step      = 4;
        $this->signOrderModel->payStatus = 2;
        $this->signOrderModel->save();

        $mainProcess                = $this->signOrderModel->mainProcessRel;
        $mainProcess->nowStepStatus = MissionTemplateEnum::STEP_STATUS_2;
        $mainProcess->save();

        // 订单日志事件
        Cache::forget(OpenShopCacheEnum::getShopManagerPwd((string)optional($this->signOrderModel->baseInfoRel)->mobile));

        event(new OrderPaymentSucceededEvent($this->signOrderModel, $this->signOrderModel->payHistoryRel));

        BuildFs::newRobot(SendFs::ROBOT_OPEN_SHOP_PART_PAY)
               ->setTitleContent('部分支付跳步骤', "订单：{$orderNo} 操作人：{$userName}")->send();

        return $this->success(['ok']);
    }

    public function skipStep(Request $request)
    {
        if (!isTest()) {
            return $this->fail(400, '仅测试环境可用');
        }

        $this->validate($request, [
            'orderNo'    => 'required|string',
            'stepStatus' => 'required|integer',
        ]);

        $orderNo    = $request->get('orderNo');
        $stepStatus = $request->get('stepStatus');

        SkipStepMultiple::doStepSkip($orderNo, $stepStatus, null);

        return $this->success();
    }
}
